package ConCurrent;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * 如何保证三个线程同时执行
 *
 * ### 使用 CyclicBarrier
 *
 * `CyclicBarrier` 是一个同步辅助类，它允许一组线程互相等待，直到到达一个公共的屏障点。`CyclicBarrier` 可以重用，即一旦所有线程到达屏障点后，屏障会重置，可以再次使用。
 *
 *  CyclicBarrier 可以通过线程数量来设置屏障，也可以通过 Runnable 来设置屏障。
 *
 *  **CyclicBarrier**：
 * - 创建一个 `CyclicBarrier` 对象，初始计数为 3。
 * - 每个线程在开始执行前调用 `barrier.await()`，等待所有线程到达屏障点。
 * - 当所有线程到达屏障点后，屏障会重置，所有线程继续执行。
 */
public class ThreadAllStartB {

    public static void main(String[] args) {
        // 创建一个 CyclicBarrier，计数为 3， 允许三个线程同时阻塞
        CyclicBarrier barrier = new CyclicBarrier(3, () -> {
            System.out.println("All threads start now");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        // 创建三个线程
        Thread threadA = new Thread(() -> {
            try {
                System.out.println("Thread A is waiting at the barrier");
                barrier.await();
                System.out.println("Thread A starts execution");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }, "ThreadA");

        Thread threadB = new Thread(() -> {
            try {
                System.out.println("Thread B is waiting at the barrier");
                barrier.await();
                System.out.println("Thread B starts execution");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }, "ThreadB");

        Thread threadC = new Thread(() -> {
            try {
                System.out.println("Thread C is waiting at the barrier");
                barrier.await();
                System.out.println("Thread C starts execution");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }, "ThreadC");

        // 启动三个线程
        threadA.start();
        threadB.start();
        threadC.start();
    }
}
